#
#   Engine.py
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; version 2 of the License.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   Copyright
#   Author: Nicholas F. Hoover
#   Contributors: Salvatore S. Gionfriddo
#   Created: 2007.08.04
#   Last Modified: 2007.08.11
#

import pygame
import GameObject
import Spawner

class Engine(object):

    def __init__(self, drawSurface):
        self.drawSurface = drawSurface
        self.spriteLists = []
        self.spawners = []
        self.collisionFunctions = []
        
    def reset(self):
        self.resetSpawners()
        
        for spriteList in self.spriteLists:
            if spriteList.emptyOnReset:
                spriteList.spriteGroup.empty()
            elif spriteList.resetOnReset:
                for sprite in spriteList.spriteGroup:
                    sprite.reset()

#SpriteLists
    def setNumberSpriteLists(self, count):
        self.spriteLists = range(count)
        
    def addSpriteList(self, index, spriteList):
        assert(spriteList.__class__ is SpriteList)
        self.spriteLists[index] = spriteList

    def addSpriteToGroup(self, index, sprite):
        self.getSpriteGroup(index).add(sprite)
        if self.spriteLists[index].sortOnAdd:
            self.getSpriteGroup(index)._spritelist.sort(GameObject.gameObjectPosCompare)
        
    def getSpriteGroup(self, index):
        return self.spriteLists[index].spriteGroup

#collisions        
    def addCollisionFunctions(self, functions):
        for function in functions:
            self.addCollisionFunction(function)
            
    def addCollisionFunction(self, function):
        assert(callable(function))
        self.collisionFunctions.append(function)

#updates
    def updateSprites(self, collision_rects, args):
        for sList in self.spriteLists:
            if sList.collidable:
                if sList.updateArgIndex >= 0:
                    sList.spriteGroup.update(collision_rects, args[sList.updateArgIndex])
                else:
                    sList.spriteGroup.update(collision_rects)
            else:
                if sList.updateArgIndex >= 0:
                    sList.spriteGroup.update(args[sList.updateArgIndex])
                else:
                    sList.spriteGroup.update()
            
    def collide(self):
        for collisionFunction in self.collisionFunctions:
            collisionFunction()

    def draw(self):
        rects = []
        for sList in self.spriteLists:
            rects += sList.spriteGroup.draw(self.drawSurface)
        return rects
    
    def update(self, args):
        self.spawn()
        
        collision_rects = []
        for sList in self.spriteLists:
            if sList.collidable:
                for sprite in sList.spriteGroup:
                    collision_rects.append(sprite.collision_rect)
                
        self.updateSprites(collision_rects, args)
        self.collide()
        #self.draw()

# SPAWNERS #
    def setSpawners(self, spawners):
        self.spawners = spawners

    def addSpawner(self, spawner):
        self.spawners.append(spawner)

    def resetSpawners(self):
        for spawner in self.spawners:
            spawner.reset()

    def spawn(self):
        for spawner in self.spawners:
            spawner.spawn()


class SpriteList(object):
    
    def __init__(self, spriteGroup, collidable = False, empty = True, reset = False, sorted = True, updateArgIndex = -1):
        self.spriteGroup = spriteGroup
        self.collidable = collidable
        self.emptyOnReset = empty
        self.resetOnReset = reset
        self.sortOnAdd = sorted
        self.updateArgIndex = updateArgIndex
            
